package dwei.ui.core
{
	import dwei.core.util.StringUtil;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	
	public class ValidateSprite extends Sprite implements IValidate
	{
//============================================================================
//PROPERTY
//============================================================================
		private var _uid:String;
		private var _nestLevel:uint;
		private var _initialized:Boolean;
		
		private var _width:int;
		private var _percentWidth:int;
		private var _height:int;
		private var _percentHeight:int;
//============================================================================
//CONSTRUCTOR
//============================================================================
		public function ValidateSprite()
		{
			super();
			_uid = StringUtil.createUID();
			_nestLevel = 0;
			_initialized = false;
		}
//============================================================================
//METHOD
//============================================================================
		//====================================================================
		//OVERRIDE
		//====================================================================
		override public function addChild(child:DisplayObject):DisplayObject
		{
			super.addChild(child);
			if (child is IValidate) IValidate(child).nestLevel = _nestLevel + 1;
			if (child is IValidate) IValidate(child).initialize();
			return child;
		}
		override public function addChildAt(child:DisplayObject, index:int):DisplayObject
		{
			super.addChildAt(child, index);
			if (child is IValidate) IValidate(child).nestLevel = _nestLevel + 1;
			if (child is IValidate) IValidate(child).initialize();
			return child;
		}
		override public function removeChild(child:DisplayObject):DisplayObject
		{
			super.removeChild(child);
			if (child is IValidate) IValidate(child).nestLevel = 0;
			return child;
		}
		override public function removeChildAt(index:int):DisplayObject
		{
			var child:DisplayObject = super.removeChildAt(index);
			if (child is IValidate) IValidate(child).nestLevel = 0;
			return child;
		}
		override public function get width():Number
		{
			return _width;
		}
		override public function set width(value:Number):void
		{
			if (value == _width) return;
			_width = value;
			if (!isNaN(_width)) _percentWidth = NaN;
			invalidateDisplayList();
			
			var p:IValidate = parent as IValidate;
			if (p != null)
			{
				p.invalidateSize();
				p.invalidateDisplayList();
			}
		}
		override public function get height():Number
		{
			return _height;
		}
		override public function set height(value:Number):void
		{
			if (value == _height) return;
			if (!isNaN(_height)) _percentHeight = NaN;
			_height = value;
			invalidateDisplayList();
			
			var p:IValidate = parent as IValidate;
			if (p != null)
			{
				p.invalidateSize();
				p.invalidateDisplayList();
			}
		}
		//====================================================================
		//PUBLIC
		//====================================================================
		public function initialize():void
		{
			if (_initialized) return;
			preInitialize();
			createChildren();
			invalidateProperties();
			invalidateSize();
			invalidateDisplayList();
		}
		public function move(x:int, y:int):void
		{
			super.x = x;
			super.y = y;
		}
		public function invalidateProperties():void
		{
			ValidateMgr.invalidateProperties(this);
		}
		public function invalidateSize():void
		{
			ValidateMgr.invalidateSize(this);
		}
		public function invalidateDisplayList():void
		{
			ValidateMgr.invalidateDisplayList(this);
		}
		public function validateProperties():void
		{
			commitProperties();
		}
		public function validateSize():void
		{
			measure();
		}
		public function validateDisplayList():void
		{
			updateDisplayList();
		}
		//====================================================================
		//PROPTECTED
		//====================================================================
		protected function preInitialize():void
		{
		}
		protected function createChildren():void
		{
		}
		protected function commitProperties():void
		{
		}
		protected function measure():void
		{
			width = super.width;
			height = super.height;
		}
		protected function updateDisplayList():void
		{
			
		}
//============================================================================
//GETTER/SETTER
//============================================================================
		
		public function get initialized():Boolean
		{
			return _initialized;
		}
		public function set initialized(value:Boolean):void
		{
			_initialized = value;
		}
		public function get nestLevel():uint
		{
			return _nestLevel;
		}
		public function set nestLevel(value:uint):void
		{
			_nestLevel = value;
			
			var child:IValidate;
			var index:int = numChildren - 1;
			while (index > -1)
			{
				child = getChildAt(index--) as IValidate;
				if (child != null) child.nestLevel = value + 1;
			}
		}
		public function get uid():String
		{
			return _uid;
		}
		public function set uid(value:String):void
		{
			_uid = value;
		}
		public function get percentWidth():int
		{
			return _percentWidth;
		}
		public function set percentWidth(value:int):void
		{
			if (value == _percentWidth) return;
			_percentWidth = value;
			if (!isNaN(_percentWidth)) _width = NaN;
			invalidateDisplayList();
			
			var p:IValidate = parent as IValidate;
			if (p != null)
			{
				p.invalidateSize();
				p.invalidateDisplayList();
			}
		}
		public function get percentHeight():int
		{
			return _percentHeight;
		}
		public function set percentHeight(value:int):void
		{
			if (value == _percentHeight) return;
			_percentHeight = value;
			if (!isNaN(_percentHeight)) _height = NaN;
			invalidateDisplayList();
			
			var p:IValidate = parent as IValidate;
			if (p != null)
			{
				p.invalidateSize();
				p.invalidateDisplayList();
			}
		}
//		public function get measuredWidth():int
//		{
//			return _measuredWidth;
//		}
//		public function set measuredWidth(value:int):void
//		{
//			_measuredWidth = value;
//		}
//		public function get measuredHeight():int
//		{
//			return _measuredHeight;
//		}
//		public function set measuredHeight(value:int):void
//		{
//			_measuredHeight = value;
//		}

	}
}